﻿using System;
using GameStructure.Contracts;
using GameStructure.Types;
using Tao.OpenGl;

namespace GameStructure.GaneState
{
    public class WaveformGraphState : IGameObject
    {
        // Position to draw the graph
        private const double X_POSITION = -100;
        private const double Y_POSITION = -100;

        // Length of the graph axis
        private const double X_LENGTH = 200;
        private const double Y_LENGTH = 200;

        // How many samples to take of the graph - this controls the smoothness
        private const double SAMPLE_SIZE = 100;

        // Frequency of the wave form plotted to the graph.
        private const double FREQUENCY = 2;
        public delegate double WaveFunction(double value);

        public WaveformGraphState()
        {
            Gl.glLineWidth(3);
            Gl.glDisable(Gl.GL_TEXTURE_2D);
        }

        public void DrawAxis()
        {
            Gl.glColor3f(1,1,1);
            Gl.glBegin(Gl.GL_LINES);
            {
                // X axis
                Gl.glVertex2d(X_POSITION, Y_POSITION);
                Gl.glVertex2d(X_POSITION + X_LENGTH, Y_POSITION);

                // Y axis
                Gl.glVertex2d(X_POSITION, Y_POSITION);
                Gl.glVertex2d(X_POSITION, Y_POSITION + Y_LENGTH);
            }
            Gl.glEnd();
        }

        public void DrawGraph(WaveFunction waveFunction, Color color)
        {
            const double xIncrement = X_LENGTH/SAMPLE_SIZE;
            var previousX = X_POSITION;
            var previousY = Y_POSITION + (0.5*Y_LENGTH);

            Gl.glColor3f(color.Red, color.Green, color.Blue);
            Gl.glBegin(Gl.GL_LINES);
            {
                for (var i = 0; i < SAMPLE_SIZE; i++)
                {
                    // Work out new X and Y positions
                    var newX = previousX + xIncrement;  // Increment one unit on the x

                    // from 0-1 how far through plotting the graph are we?
                    var percentDone = (i/SAMPLE_SIZE);
                    var percentRadians = percentDone*(Math.PI*FREQUENCY);

                    // Scale the wave value by the half the length
                    var newY = Y_POSITION + waveFunction(percentRadians)*(Y_LENGTH/2);

                    // Ignore the first value because the previous X and Y haven't been worked out yet.
                    if(i>1)
                    {
                        Gl.glVertex2d(previousX, previousY);
                        Gl.glVertex2d(newX, newY);
                    }

                    // Store the previous position
                    previousX = newX;
                    previousY = newY;
                }
            }
            Gl.glEnd();
        }

        public void Update(double elapsedTime)
        {
            
        }

        public void Render()
        {
            DrawAxis();
            DrawGraph(Math.Sin, new Color(1,0,0,1));
            DrawGraph(Math.Cos, new Color(0,0.5f,0.5f,1));

            // Uncomment the below lines and check the graph formed.
            //DrawGraph(delegate(double value)
            //{
            //    return (Math.Sin(value) + Math.Cos(value)) * 0.5;
            //}, new Color(0.5f, 0.5f, 1, 1));

            // Try this one too
            //DrawGraph(delegate(double value)
            //{
            //    return (Math.Sin(value) + Math.Sin(value + value)) * 0.5;
            //}, new Color(0.5f, 0.5f, 1, 1));
        }
    }
}
